#include "AST.h"
#include <iostream>
#include <vector>

using namespace std;

typedef int INTEGER;
typedef int INDEX;
typedef string STRING;
typedef bool BOOLEAN;
typedef string NODETYPE;
typedef string LINKTYPE;

	BOOLEAN AST::setRoot(TNode *node){
		(*node).setRoot();
		_root = node;
		(*_root).setLevel(0);
		return true;
	}
	TNode* AST::getRoot(){
		return _root;
	}
	void AST::setTotalLineNum(INTEGER num){
		_totalLineNum = num;
	}
	INTEGER AST::getTotalLineNum(){
		return _totalLineNum;
	}
	
	TNode* AST::getNodeFromLineNum(TNode* node,INTEGER num){
		TNode* numNode = NULL;
		if((*node).getProcLine()==num)
			return node;
		else {
			if((*node).getNumOfMoreChild()>0){
				for(int i=0;i<(*node).getNumOfMoreChild();i++){
				numNode = getNodeFromLineNum((*node).getMoreChildren()[i],num);
				    if (numNode != NULL){
					    return numNode;
				    }
			    }
		    }
		}
		return numNode;
	}
	vector<INDEX> AST::getVarsFromLineNum(INTEGER lineNum){
		vector<INDEX> result =vector<INDEX>();
		TNode* node =getNodeFromLineNum(_root,lineNum);
		return getVarsFromLineNumTool(&result,lineNum,node);

	}
	vector<INDEX> AST::getVarsFromLineNumTool(vector<INDEX>* v,INTEGER lineNum,TNode* node){
		if((*node).getNumOfMoreChild()>0){
			if(((*node).getProcLine()==-1||(*node).getProcLine()==lineNum)&&((*node).getNodeType().compare("Variable")==0)&&((*node).getIndex()!=-1)){
				(*v).push_back((*node).getIndex());
			}
			for(int i=0;i<(*node).getNumOfMoreChild();i++){
				    *v=getVarsFromLineNumTool(v,lineNum,(*node).getMoreChildren()[i]);
			    }
			
		}else{
			if(((*node).getProcLine()==-1||(*node).getProcLine()==lineNum)&&((*node).getNodeType().compare("Variable")==0)&&((*node).getIndex()!=-1)){
				(*v).push_back((*node).getIndex());
				//(*v).push_back(51);
			}
		}
		return *v;
	}
	
	TNode* AST::createNode(NODETYPE nodeType){
		TNode node = TNode();
		node.setNodeType(nodeType);
		return &node;
	}
	LINKTYPE AST::createLink(TNode *fromNode, TNode *toNode, LINKTYPE linkType){
		
		if( linkType.compare("isParent")==0){
			(*fromNode).insertMoreChildren(toNode);
			(*toNode).setParent(fromNode);
			(*fromNode).setLevel((*toNode).getLevel()-1);
			return "isParent";
		}
		if( linkType.compare("isChild")==0){
			
			(*toNode).insertMoreChildren(fromNode);
			(*fromNode).setParent(toNode);
			(*fromNode).setLevel((*toNode).getLevel()+1);
			return "isChild";
		}
		if(linkType.compare( "isLeftSibling")==0){
			(*fromNode).setRightSibling(toNode);
			(*toNode).setLeftSibling(fromNode);
			(*fromNode).setLevel((*toNode).getLevel());
			return "isLeftSibling";
		}
		if(linkType.compare("isRightSibling")==0){
			(*fromNode).setLeftSibling(toNode);
			(*toNode).setRightSibling(fromNode);
			(*fromNode).setLevel((*toNode).getLevel());
			return "isRightSibling";
		}

		
		return "Error";
	}
	TNode* AST::getParent(TNode *node){
		return (*node).getParent();
	}


	vector<TNode*> AST::getParentStar(TNode* node){
		vector<TNode*> parents= vector<TNode*>();
		return getParentStarVector(&parents, node);
	}
	vector<TNode*> AST::getParentStarVector(vector<TNode*>* parents, TNode* node){
		if((*node).getParent() != NULL){
			(*parents).push_back((*node).getParent());
			return getParentStarVector(parents, (*node).getParent());
		}else{
			return *parents;
		}
	}

	TNode* AST::getFollow(TNode *node){
		return (*node).getRightSibling();
	}
	TNode* AST::getFollowBy(TNode* node){
		return (*node).getLeftSibling();
	}
	vector<TNode*> AST::getFollowStar(TNode *node){
		vector<TNode*> rightSiblings = vector<TNode*>();
		return getFollowStarVector(&rightSiblings, node);
	}
	vector<TNode*> AST::getFollowStarVector(vector<TNode*>* rightSiblings, TNode* node){
		if((*node).getRightSibling()!=NULL){
			(*rightSiblings).push_back((*node).getRightSibling());
			return  getFollowStarVector(rightSiblings, (*node).getRightSibling());
		}
		return *rightSiblings;
	}
	vector<TNode*> AST::getFollowByStar(TNode* node){
		vector<TNode*> leftSiblings = vector<TNode*>();
		return getFollowByStarVector(&leftSiblings, node);
	}
	vector<TNode*> AST::getFollowByStarVector(vector<TNode*>* leftSiblings, TNode* node){
		if((*node).getLeftSibling()!=NULL){
			(*leftSiblings).push_back((*node).getLeftSibling());
			return  getFollowByStarVector(leftSiblings, (*node).getLeftSibling());
		}
		return *leftSiblings;
	}
	TNode** AST::getDirectMoreChildren(TNode *node){
		return (*node).getMoreChildren();
	}
	vector<TNode**> AST::getMoreChildrenStar(TNode* node){
		vector<TNode**> moreChildren = vector<TNode**>();
		return getMoreChildrenStarVector(&moreChildren,node);
	}
	vector<TNode**> AST::getMoreChildrenStarVector(vector<TNode**>* moreChildren,TNode* node){
		if((*node).getNumOfMoreChild()>0){
			(*moreChildren).push_back((*node).getMoreChildren());
			for(int i=0;i<(*node).getNumOfMoreChild();i++){
				getMoreChildrenStarVector( moreChildren,(*node).getMoreChildren()[i]);
			}
		}
		return *moreChildren;
	}